home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / emula / arosdv19.lha / AROS / dos / createnewproc.c < prev    next >
C/C++ Source or Header  |  1996-10-24  |  9KB  |  312 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: createnewproc.c,v 1.9 1996/10/24 15:50:25 aros Exp $
  4.     $Log: createnewproc.c,v $
  5.     Revision 1.9  1996/10/24 15:50:25  aros
  6.     Use the official AROS macros over the __AROS versions.
  7.  
  8.     Revision 1.8  1996/10/23 14:22:23  aros
  9.     Use the systems' stacksize
  10.  
  11.     Revision 1.7  1996/10/10 13:19:33  digulla
  12.     Several IPTR/BPTR-Casts (Fleischer)
  13.  
  14.     Revision 1.6  1996/09/21 14:15:05  digulla
  15.     Number TagList
  16.     New tag: NP_UserData
  17.     Don't free non-allocated resources.
  18.  
  19.     Revision 1.5  1996/09/13 17:50:05  digulla
  20.     Use IPTR
  21.  
  22.     Revision 1.4  1996/09/11 12:56:39  digulla
  23.     Bugfix and a lot of new checks by M. Fleischer
  24.  
  25.     Desc:
  26.     Lang: english
  27. */
  28. #include <exec/memory.h>
  29. #include <clib/exec_protos.h>
  30. #include <dos/dosextens.h>
  31. #include <dos/filesystem.h>
  32. #include <dos/dostags.h>
  33. #include <clib/dos_protos.h>
  34. #include <utility/tagitem.h>
  35. #include <clib/utility_protos.h>
  36. #include "dos_intern.h"
  37.  
  38. #define NEWLIST(l)                          \
  39. ((l)->lh_Head=(struct Node *)&(l)->lh_Tail, \
  40.  (l)->lh_Tail=NULL,                         \
  41.  (l)->lh_TailPred=(struct Node *)(l))
  42.  
  43. static void KillCurrentProcess(void);
  44. struct Process *AddProcess(struct Process *process, STRPTR argPtr,
  45. ULONG argSize, APTR initialPC, APTR finalPC, struct DosLibrary *DOSBase);
  46.  
  47. /*****************************************************************************
  48.  
  49.     NAME */
  50.     #include <clib/dos_protos.h>
  51.  
  52.     AROS_LH1(struct Process *, CreateNewProc,
  53.  
  54. /*  SYNOPSIS */
  55.     AROS_LHA(struct TagItem *, tags, D1),
  56.  
  57. /*  LOCATION */
  58.     struct DosLibrary *, DOSBase, 83, Dos)
  59.  
  60. /*  FUNCTION
  61.     Create a new process using the tagitem array.
  62.  
  63.     INPUTS
  64.     tags - information on the new process.
  65.  
  66.     RESULT
  67.     Pointer to the new process or NULL on error.
  68.  
  69.     NOTES
  70.  
  71.     EXAMPLE
  72.  
  73.     BUGS
  74.  
  75.     SEE ALSO
  76.  
  77.     INTERNALS
  78.  
  79.     HISTORY
  80.     29-10-95    digulla automatically created from
  81.                 dos_lib.fd and clib/dos_protos.h
  82.  
  83. *****************************************************************************/
  84. {
  85.     AROS_LIBFUNC_INIT
  86.     AROS_LIBBASE_EXT_DECL(struct DosLibrary *,DOSBase)
  87.  
  88.     /* Allocated resources */
  89.     struct Process *process=NULL;
  90.     BPTR input=0, output=0, curdir=0;
  91.     STRPTR stack=NULL, name=NULL, argptr=NULL;
  92.     ULONG namesize, argsize=0;
  93.     struct MemList *memlist=NULL;
  94.     struct CommandLineInterface *cli=NULL;
  95.  
  96.     struct Process *me=(struct Process *)FindTask(NULL);
  97.     STRPTR s;
  98.     BPTR *oldpath, *newpath, *nextpath;
  99.  
  100.     struct TagItem defaults[]=
  101.     {
  102.     /* 0 */    { NP_Seglist,       0 },
  103.     /* 1 */    { NP_Entry,       (IPTR)NULL },
  104.     /* 2 */    { NP_Input,       ~0ul },
  105.     /* 3 */    { NP_CloseInput,    1 },
  106.     /* 4 */    { NP_Output,       ~0ul },
  107.     /* 5 */    { NP_CloseOutput,   1 },
  108.     /* 6 */    { NP_Error,       0 },
  109.     /* 7 */    { NP_CloseError,    1 },
  110.     /* 8 */    { NP_CurrentDir,    ~0ul },
  111.     /* 9 */    { NP_StackSize,       AROS_STACKSIZE },
  112.     /*11 */    { NP_Name,       (IPTR)"New Process" },
  113.     /*12 */    { NP_Priority,       me->pr_Task.tc_Node.ln_Pri },
  114.     /*13 */    { NP_Arguments,       (IPTR)NULL },
  115.     /*14 */    { NP_Cli,       0 },
  116.     /*15 */    { NP_UserData,       (IPTR)NULL },
  117.     { TAG_END, 0 }
  118.     };
  119.     /* C has no exceptions. This is a simple replacement. */
  120. #define ERROR_IF(a)  if(a) goto error  /* Throw a generic error. */
  121. #define ENOMEM_IF(a) if(a) goto enomem /* Throw out of memory. */
  122.  
  123.     ApplyTagChanges(defaults,tags);
  124.  
  125.     process=(struct Process *)AllocMem(sizeof(struct Process),MEMF_PUBLIC|MEMF_CLEAR);
  126.     ENOMEM_IF(process==NULL);
  127.     stack=AllocMem(defaults[9].ti_Data,MEMF_PUBLIC);
  128.     ENOMEM_IF(stack==NULL);
  129.     s=(STRPTR)defaults[10].ti_Data;
  130.     while(*s++)
  131.     ;
  132.     namesize=s-(STRPTR)defaults[10].ti_Data;
  133.     name=AllocMem(namesize,MEMF_PUBLIC);
  134.     ENOMEM_IF(name==NULL);
  135.     s=(STRPTR)defaults[12].ti_Data;
  136.     if(s!=NULL)
  137.     {
  138.     while(*s++)
  139.         ;
  140.     argsize=s-(STRPTR)defaults[12].ti_Data;
  141.     argptr=(STRPTR)AllocVec(argsize,MEMF_PUBLIC);
  142.     ENOMEM_IF(argptr==NULL);
  143.     }
  144.     memlist=AllocMem(sizeof(struct MemList)+2*sizeof(struct MemEntry),MEMF_ANY);
  145.     ENOMEM_IF(memlist==NULL);
  146.     if(defaults[13].ti_Data)
  147.     {
  148.     cli=(struct CommandLineInterface *)AllocDosObject(DOS_CLI,NULL);
  149.     ENOMEM_IF(cli==NULL);
  150.     oldpath=NULL;
  151.     if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  152.     {
  153.         struct CommandLineInterface *oldcli=Cli();
  154.         if(oldcli!=NULL)
  155.         oldpath=BADDR(oldcli->cli_CommandDir);
  156.     }
  157.     newpath=&cli->cli_CommandDir;
  158.     while(oldpath!=NULL)
  159.     {
  160.         nextpath=AllocVec(2*sizeof(BPTR),MEMF_CLEAR);
  161.         ENOMEM_IF(nextpath==NULL);
  162.         newpath[0]=MKBADDR(nextpath);
  163.         nextpath[1]=DupLock(oldpath[1]);
  164.         ERROR_IF(!nextpath[1]);
  165.         newpath=nextpath;
  166.         oldpath=BADDR(oldpath[0]);
  167.     }
  168.     }
  169.     if(defaults[2].ti_Data==~0ul)
  170.     {
  171.     input=Open("NIL:",MODE_OLDFILE);
  172.     ERROR_IF(!input);
  173.     defaults[2].ti_Data=(IPTR)input;
  174.     }
  175.     if(defaults[4].ti_Data==~0ul)
  176.     {
  177.     output=Open("NIL:",MODE_NEWFILE);
  178.     ERROR_IF(!output);
  179.     defaults[4].ti_Data=(IPTR)output;
  180.     }
  181.     if(defaults[8].ti_Data==~0ul)
  182.     {
  183.     if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  184.     {
  185.         curdir=Lock("",SHARED_LOCK);
  186.         ERROR_IF(!curdir);
  187.         defaults[8].ti_Data=(IPTR)curdir;
  188.     }else
  189.         defaults[8].ti_Data=0;
  190.     }
  191.  
  192.     CopyMem((APTR)defaults[10].ti_Data,name,namesize);
  193.     CopyMem((APTR)defaults[12].ti_Data,argptr,argsize);
  194.     process->pr_Task.tc_Node.ln_Type=NT_PROCESS;
  195.     process->pr_Task.tc_Node.ln_Name=name;
  196.     process->pr_Task.tc_Node.ln_Pri=defaults[11].ti_Data;
  197.     process->pr_Task.tc_SPLower=stack;
  198.     process->pr_Task.tc_SPUpper=stack+defaults[9].ti_Data;
  199.  
  200.  
  201. /*  process->pr_ReturnAddr; */
  202.     NEWLIST(&process->pr_Task.tc_MemEntry);
  203.     memlist->ml_NumEntries=3;
  204.     memlist->ml_ME[0].me_Addr=process;
  205.     memlist->ml_ME[0].me_Length=sizeof(struct Process);
  206.     memlist->ml_ME[1].me_Addr=stack;
  207.     memlist->ml_ME[1].me_Length=defaults[9].ti_Data;
  208.     memlist->ml_ME[2].me_Addr=name;
  209.     memlist->ml_ME[2].me_Length=namesize;
  210.     AddHead(&process->pr_Task.tc_MemEntry,&memlist->ml_Node);
  211.     process->pr_MsgPort.mp_Node.ln_Type=NT_MSGPORT;
  212.     process->pr_MsgPort.mp_Flags=PA_SIGNAL;
  213.     process->pr_MsgPort.mp_SigBit=SIGB_DOS;
  214.     process->pr_MsgPort.mp_SigTask=process;
  215.     NEWLIST(&process->pr_MsgPort.mp_MsgList);
  216.     process->pr_SegList=(BPTR)defaults[0].ti_Data;
  217.     process->pr_StackSize=defaults[9].ti_Data;
  218.     process->pr_GlobVec=NULL;
  219.     Forbid();
  220.     process->pr_TaskNum=DOSBase->dl_ProcCnt++;
  221.     Permit();
  222.     process->pr_StackBase=MKBADDR(process->pr_Task.tc_SPUpper);
  223.     process->pr_Result2=0;
  224.     process->pr_CurrentDir=(BPTR)defaults[8].ti_Data;
  225.     process->pr_CIS=(BPTR)defaults[2].ti_Data;
  226.     process->pr_COS=(BPTR)defaults[4].ti_Data;
  227.     process->pr_CES=(BPTR)defaults[6].ti_Data;
  228.  
  229.     process->pr_Task.tc_UserData = (APTR)defaults[15].ti_Data;
  230.  
  231. /*  process->pr_ConsoleTask=; */
  232. /*  process->pr_FileSystemTask=; */
  233.     process->pr_CLI=MKBADDR(cli);
  234. /*  process->pr_PktWait=; */
  235. /*  process->pr_WindowPtr=; */
  236. /*  process->pr_HomeDir=; */
  237.     process->pr_Flags=(defaults[3].ti_Data?PRF_CLOSEINPUT:0)|
  238.               (defaults[5].ti_Data?PRF_CLOSEOUTPUT:0)|
  239.               (defaults[7].ti_Data?PRF_CLOSEERROR:0)|
  240.               (defaults[13].ti_Data?PRF_FREECLI:0)|
  241.               PRF_FREEARGS|PRF_FREESEGLIST|PRF_FREECURRDIR;
  242. /*  process->pr_ExitCode=; */
  243. /*  process->pr_ExitData=; */
  244.     process->pr_Arguments=argptr;
  245.     NEWLIST((struct List *)&process->pr_LocalVars);
  246.     process->pr_ShellPrivate=0;
  247.  
  248.     if(AddProcess(process,argptr,argsize,defaults[0].ti_Data?
  249.           (BPTR *)BADDR(defaults[0].ti_Data)+1:
  250.           (BPTR *)defaults[1].ti_Data,KillCurrentProcess,
  251.           DOSBase)!=NULL)
  252.     return process;
  253.  
  254.     /* Fall through */
  255. enomem:
  256.     if(me->pr_Task.tc_Node.ln_Type==NT_PROCESS)
  257.     me->pr_Result2=ERROR_NO_FREE_STORE;
  258. error:
  259.     if (cli)
  260.     FreeDosObject(DOS_CLI,cli);
  261.  
  262.     if (curdir)
  263.     UnLock(curdir);
  264.  
  265.     if (output)
  266.     Close(output);
  267.  
  268.     if (input)
  269.     Close(input);
  270.  
  271.     if (argptr)
  272.     FreeVec(argptr);
  273.  
  274.     if(memlist!=NULL)
  275.     FreeMem(memlist,sizeof(struct MemList)+2*sizeof(struct MemEntry));
  276.  
  277.     if(name!=NULL)
  278.     FreeMem(name,namesize);
  279.  
  280.     if(stack!=NULL)
  281.     FreeMem(stack,defaults[9].ti_Data);
  282.  
  283.     if(process!=NULL)
  284.     FreeMem(process,sizeof(struct Process));
  285.  
  286.     return NULL;
  287.     AROS_LIBFUNC_EXIT
  288. } /* CreateNewProc */
  289.  
  290. static void KillCurrentProcess(void)
  291. {
  292.     /* I need the global here because there is no local way to get it */
  293.     extern struct DosLibrary *DOSBase;
  294.     struct Process *me=(struct Process *)FindTask(NULL);
  295.  
  296.     if(me->pr_Flags&PRF_CLOSEINPUT)
  297.     Close(me->pr_CIS);
  298.     if(me->pr_Flags&PRF_CLOSEOUTPUT)
  299.     Close(me->pr_COS);
  300.     if(me->pr_Flags&PRF_CLOSEERROR)
  301.     Close(me->pr_CES);
  302.     if(me->pr_Flags&PRF_FREEARGS)
  303.     FreeVec(me->pr_Arguments);
  304.     if(me->pr_Flags&PRF_FREESEGLIST)
  305.     UnLoadSeg(me->pr_SegList);
  306.     if(me->pr_Flags&PRF_FREECURRDIR)
  307.     UnLock(me->pr_CurrentDir);
  308.     if(me->pr_Flags&PRF_FREECLI)
  309.     FreeDosObject(DOS_CLI,BADDR(me->pr_CLI));
  310.     RemTask(NULL);
  311. }
  312.